import base64
import json
import pickle

from django.http import JsonResponse
from django.shortcuts import render

# Create your views here.
from django.views import View
from django_redis import get_redis_connection

from apps.goods.models import SKU


class CartsView(View):
    """购物车管理"""

    def post(self, request):
        """添加购物车"""
        # 1.接受数据
        data = json.loads(request.body.decode())
        sku_id = data.get('sku_id')
        count = data.get('count')
        # 2.验证数据

        try:
            sku = SKU.objects.get(id=sku_id)
        except SKU.DoesNotExist:
            return JsonResponse({'code': 400, 'errmsg': '查无此商品'})

        # 类型强制转换
        try:
            count = int(count)
        except Exception:
            count = 1
        user = request.user
        if user.is_authenticated:
            # 4.登录用户保存redis
            #     4.1 连接redis
            redis_cli = get_redis_connection('carts')

            pipeline = redis_cli.pipeline()
            #     4.2 操作hash
            # redis_cli.hset(key,field,value)
            # 1. 先获取之前的数据，然后累加
            # 2.
            # redis_cli.hset('carts_%s'%user.id,sku_id,count)
            # hincrby
            # 会进行累加操作
            pipeline.hincrby('carts_%s' % user.id, sku_id, count)
            #     4.3 操作set
            # 默认就是选中
            pipeline.sadd('selected_%s' % user.id, sku_id)

            # 一定要执行！！！
            pipeline.execute()
            #     4.4 返回响应
            return JsonResponse({'code': 0, 'errmsg': 'ok'})
        else:
            # 5.未登录用户保存cookie
            """

                cookie:
                    {
                        sku_id: {count:xxx,selected:xxxx},
                        sku_id: {count:xxx,selected:xxxx},
                        sku_id: {count:xxx,selected:xxxx},
                    }

            """
            cookie_carts = request.COOKIES.get('carts')
            if cookie_carts:
                # 对加密的数据解密
                carts = pickle.loads(base64.b64decode(cookie_carts))
            else:
                #     5.1 先有cookie字典
                carts = {}

            # 判断新增的商品 有没有在购物车里

            if sku_id in carts:
                # 购物车中 已经有该商品id
                # 数量累加
                ## {16： {count:3,selected:True}}
                origin_count = carts[sku_id]['count']
                count += origin_count

            carts[sku_id] = {
                'count': count,
                'selected': True
            }

            carts_bytes = pickle.dumps(carts)
            #     5.3 bytes类型数据base64编码

            base64encode = base64.b64encode(carts_bytes)
            #     5.4 设置cookie
            response = JsonResponse({'code': 0, 'errmsg': 'ok'})
            # key, value='', max_age=None
            # base64encode.decode() 的作用是 将bytes类型转换为 str
            # 因为 value的数据是 str数据
            response.set_cookie('carts', base64encode.decode(), max_age=3600 * 24 * 12)
            #     5.5 返回响应
            return response

    def get(self, request):
        """展示购物车"""
        user = request.user
        if user.is_authenticated:
            redis_conn = get_redis_connection('carts')
            redis_cart = redis_conn.hgetall('carts_%s' % user.id)

            # 获取redis中的选中状态
            cart_selected = redis_conn.smembers('selected_%s' % user.id)
            carts = {}
            for sku_id, count in redis_cart.items():
                carts[int(sku_id)] = {
                    'count': int(count),
                    'selected': sku_id in cart_selected
                }

        else:
            # 3.未登录用户查询cookie
            #     3.1 读取cookie数据
            cookie_carts = request.COOKIES.get('carts')
            #     3.2 判断是否存在购物车数据
            if cookie_carts is not None:
                #         如果存在，则解码            {sku_id:{count:xxx,selected:xxx}}
                carts = pickle.loads(base64.b64decode(cookie_carts))
            else:
                #         如果不存在，初始化空字典
                carts = {}

        # {sku_id: {count: xxx, selected: xxx}}
        # 4 根据商品id查询商品信息
        # 可以直接遍历 carts
        # 也可以获取 字典的最外层的key，最外层的所有key就是商品id
        sku_ids = carts.keys()
        skus = SKU.objects.filter(id__in=sku_ids)
        sku_list = []
        for sku in skus:
            # 5 将对象数据转换为字典数据
            sku_list.append({
                'id': sku.id,
                'price': sku.price,
                'name': sku.name,
                'default_image_url': sku.default_image.url,
                'selected': carts[sku.id]['selected'],  # 选中状态
                'count': int(carts[sku.id]['count']),  # 数量 强制转换一下
                'amount': sku.price * carts[sku.id]['count']  # 总价格
            })
        # 6 返回响应
        return JsonResponse({'code': 0, 'errmsg': 'ok', 'cart_skus': sku_list})

    """
    1.获取用户信息
    2.接收数据
    3.验证数据
    4.登录用户更新redis
        4.1 连接redis
        4.2 hash
        4.3 set
        4.4 返回响应
    5.未登录用户更新cookie
        5.1 先读取购物车数据
            判断有没有。
            如果有则解密数据
            如果没有则初始化一个空字典
        5.2 更新数据
        5.3 重新最字典进行编码和base64加密
        5.4 设置cookie
        5.5 返回响应
    """

    def put(self, request):
        # 1.获取用户信息
        user = request.user
        # 2.接收数据
        data = json.loads(request.body.decode())
        sku_id = data.get('sku_id')
        count = data.get('count')
        selected = data.get('selected')
        # 3.验证数据
        if not all([sku_id, count]):
            return JsonResponse({'code': 400, 'errmsg': '参数不全'})

        try:
            SKU.objects.get(id=sku_id)
        except SKU.DoesNotExist:
            return JsonResponse({'code': 400, 'errmsg': '没有此商品'})

        try:
            count = int(count)
        except Exception:
            count = 1

        if user.is_authenticated:
            # 4.登录用户更新redis
            #     4.1 连接redis
            redis_cli = get_redis_connection('carts')
            #     4.2 hash
            redis_cli.hset('carts_%s' % user.id, sku_id, count)
            #     4.3 set
            if selected:
                redis_cli.sadd('selected_%s' % user.id, sku_id)
            else:
                redis_cli.srem('selected_%s' % user.id, sku_id)
            #     4.4 返回响应
            return JsonResponse({'code': 0, 'errmsg': 'ok', 'cart_sku': {'count': count, 'selected': selected}})

        else:
            # 5.未登录用户更新cookie
            #     5.1 先读取购物车数据
            cookie_cart = request.COOKIES.get('carts')
            #         判断有没有。
            if cookie_cart is not None:
                #         如果有则解密数据
                carts = pickle.loads(base64.b64decode(cookie_cart))
            else:
                #         如果没有则初始化一个空字典
                carts = {}

            #     5.2 更新数据
            # {sku_id: {count:xxx,selected:xxx}}
            if sku_id in carts:
                carts[sku_id] = {
                    'count': count,
                    'selected': selected
                }
            #     5.3 重新最字典进行编码和base64加密
            new_carts = base64.b64encode(pickle.dumps(carts))
            #     5.4 设置cookie
            response = JsonResponse({'code': 0, 'errmsg': 'ok', 'cart_sku': {'count': count, 'selected': selected}})
            response.set_cookie('carts', new_carts.decode(), max_age=14 * 24 * 3600)
            #     5.5 返回响应
            return response

    """
    1.接收请求
    2.验证参数
    3.根据用户状态
    4.登录用户操作redis
        4.1 连接redis
        4.2 hash
        4.3 set
        4.4 返回响应
    5.未登录用户操作cookie
        5.1 读取cookie中的购物车数据
        判断数据是否存在
        存在则解码
        不存在则初始化字典
        5.2 删除数据 {}
        5.3 我们需要对字典数据进行编码和base64的处理
        5.4 设置cookie
        5.5 返回响应

    """

    def delete(self, request):
        # 1.接收请求
        data = json.loads(request.body.decode())
        # 2.验证参数
        sku_id = data.get('sku_id')
        try:
            SKU.objects.get(pk=sku_id)  # pk primary key
        except SKU.DoesNotExist:
            return JsonResponse({'code': 400, 'errmsg': '没有此商品'})
        # 3.根据用户状态
        user = request.user
        if user.is_authenticated:

            # 4.登录用户操作redis
            #     4.1 连接redis
            redis_cli = get_redis_connection('carts')
            #     4.2 hash
            redis_cli.hdel('carts_%s' % user.id, sku_id)
            #     4.3 set
            redis_cli.srem('selected_%s' % user.id, sku_id)
            #     4.4 返回响应
            return JsonResponse({'code': 0, 'errmsg': 'ok'})

        else:
            # 5.未登录用户操作cookie
            #     5.1 读取cookie中的购物车数据
            cookie_cart = request.COOKIES.get('carts')
            #     判断数据是否存在
            if cookie_cart is not None:
                #     存在则解码
                carts = pickle.loads(base64.b64decode(cookie_cart))
            else:
                #     不存在则初始化字典
                carts = {}
            #     5.2 删除数据 {}
            del carts[sku_id]
            #     5.3 我们需要对字典数据进行编码和base64的处理
            new_carts = base64.b64encode(pickle.dumps(carts))
            #     5.4 设置cookie
            response = JsonResponse({'code': 0, 'errmsg': 'ok'})
            response.set_cookie('carts', new_carts.decode(), max_age=14 * 24 * 3600)
            #     5.5 返回响应
            return response
